<script setup>
import { computed, onMounted, ref, useI18n } from "#imports";
import { Plus } from "@element-plus/icons-vue";
import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  CancelCourseOrder,
  GetCourseOrderPage,
  PayCourseOrder,
  UploadCourseOrder,
} from "~/apis/admin";

definePageMeta({
  title: "课程订单",
  en_title: "Course Orders",
  zh_hk_title: "課程訂單",
  ssr: true,
  isTokenCheck: true,
});

const { t } = useI18n();

const loading = ref(false);
const statusOptions = [
  { key: "pending", value: 0 },
  { key: "paid", value: 1 },
  { key: "canceled", value: 2 },
  { key: "refunded", value: 3 },
];
const activeStatus = ref(statusOptions[0].value);
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);
const dialogVisible = ref(false);
const currentOrder = ref(null);
const orders = ref([]);
const actionLoading = ref(false);
const payDialogVisible = ref(false);
const payOrder = ref(null);
const paySubmitting = ref(false);
const payReceiptFileList = ref([]);
const payReceiptUrls = ref([]);
const payUploadError = ref(false);

const userStore = useStore.userStore();

const tabs = computed(() =>
  statusOptions.map((item) => ({
    id: item.value,
    text: t(`courseOrder.tabs.${item.key}`),
  }))
);

const statusKeyMap = computed(() =>
  statusOptions.reduce((result, item) => {
    result[item.value] = item.key;
    return result;
  }, {})
);

const courseTypeMap = computed(() => ({
  1: t("courseDetail.typeGroup"),
  2: t("courseDetail.typePrivate"),
  3: t("courseDetail.typeTrial"),
  4: t("courseDetail.typeTemporary"),
  5: t("courseDetail.typePackage"),
}));

const scheduleTypeMap = computed(() => ({
  1: t("courseOrder.scheduleType.fixed"),
  2: t("courseOrder.scheduleType.package"),
}));

const payWayMap = computed(() => ({
  0: t("courseOrder.paymentMethodMap.online"),
  1: t("courseOrder.paymentMethodMap.offline"),
}));

const payChannelMap = computed(() => ({
  1: t("courseOrder.paymentMethodMap.wechat"),
  2: t("courseOrder.paymentMethodMap.alipay"),
  3: t("courseOrder.paymentMethodMap.bank"),
}));

const getStatusKey = (status) => statusKeyMap.value[Number(status)] || "pending";
const getStatusText = (order) => t(`courseOrder.status.${getStatusKey(order.status)}`);
const getStatusClass = (order) => `status-${getStatusKey(order.status)}`;

const getCourseTypeLabel = (type) => courseTypeMap.value[Number(type)] || "--";
const getScheduleTypeLabel = (type) => scheduleTypeMap.value[Number(type)] || "--";
const getPaymentMethodLabel = (order) => {
  const channel = Number(order?.payChannel);
  if (!Number.isNaN(channel) && payChannelMap.value[channel]) {
    return payChannelMap.value[channel];
  }
  const way = Number(order?.payWay);
  if (!Number.isNaN(way) && payWayMap.value[way] !== undefined) {
    return payWayMap.value[way];
  }
  return "--";
};

const renderStudents = (students) => {
  if (!students || !students.length) return "--";
  const names = students
    .map((student) => [student.nameC, student.mobile].filter(Boolean).join("/"))
    .filter(Boolean);
  return names.length ? names.join("、") : "--";
};

const mergeNameAndPhone = (name, phone) => {
  if (!name && !phone) return "--";
  return [name, phone].filter(Boolean).join(" ");
};

const formatDateTime = (value) => {
  if (!value) return "--";
  return dayjs(value).format("YYYY/MM/DD HH:mm:ss");
};

const formatDate = (value) => {
  if (!value) return "--";
  return dayjs(value).format("YYYY/MM/DD");
};

const formatAmount = (value) => {
  if (value === undefined || value === null || Number.isNaN(Number(value))) {
    return "--";
  }
  const amount = Number(value);
  const prefix = amount < 0 ? "-" : "";
  return `${prefix}¥${Math.abs(amount).toFixed(2)}`;
};

const renderSessions = (count) => {
  if (count === undefined || count === null) return "--";
  return t("courseOrder.sessionUnit", { count });
};

const renderValidDays = (days) => {
  if (days === undefined || days === null) return "--";
  return t("courseOrder.validDaysUnit", { days });
};

const fetchOrders = async () => {
  loading.value = true;
  try {
    const res = await GetCourseOrderPage({
      status: activeStatus.value,
      pageNo: currentPage.value,
      pageSize: pageSize.value,
      userId: userStore.user.id,
    });
    orders.value = res?.data?.list || [];
    total.value = res?.data?.total || 0;
  } catch (error) {
    orders.value = [];
    total.value = 0;
  } finally {
    loading.value = false;
  }
};

const handleTabChange = (name) => {
  activeStatus.value = Number(name);
  currentPage.value = 1;
  fetchOrders();
};

const handlePageChange = ({ currentPage: page, pageSize: size }) => {
  currentPage.value = page;
  pageSize.value = size;
  fetchOrders();
};

const openDetail = (order) => {
  currentOrder.value = order;
  dialogVisible.value = true;
};

const resetPayDialog = () => {
  payOrder.value = null;
  payReceiptFileList.value = [];
  payReceiptUrls.value = [];
  paySubmitting.value = false;
  payUploadError.value = false;
};

const handlePay = (order) => {
  resetPayDialog();
  payOrder.value = order;
  payDialogVisible.value = true;
};

const submitPay = async () => {
  if (!payOrder.value || paySubmitting.value) return;
  if (!payReceiptUrls.value.length) {
    payUploadError.value = true;
    return;
  }
  payUploadError.value = false;
  paySubmitting.value = true;
  try {
    await PayCourseOrder({
      id: payOrder.value.id,
      payWay: payOrder.value.payWay,
      payChannel: payOrder.value.payChannel,
      receiptRecord: payReceiptUrls.value.join(","),
    });
    ElMessage.success(t("courseOrder.paySuccess"));
    payDialogVisible.value = false;
    await fetchOrders();
  } catch (error) {
    ElMessage.error(error?.msg || error?.message || t("courseOrder.payFailed"));
  } finally {
    paySubmitting.value = false;
  }
};

const beforeReceiptUpload = (file) => {
  const isImg = /^image\//.test(file.type);
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isImg) ElMessage.error(t("courseOrder.uploadImageOnly"));
  if (!isLt10M) ElMessage.error(t("courseOrder.uploadSizeLimit"));
  return isImg && isLt10M;
};

const onReceiptUpload = async (option) => {
  const formData = new FormData();
  formData.append("file", option.file);
  try {
    const res = await UploadCourseOrder(formData);
    if (res.code === 0) {
      const data = res.data;
      const url = data?.url || data?.path || data?.fileUrl || data;
      payReceiptUrls.value.push(url);
      payReceiptFileList.value = [...payReceiptFileList.value, { name: option.file.name, url }];
      payUploadError.value = false;
      option.onSuccess(data, option.file);
    } else {
      option.onError(new Error(res.msg || t("courseOrder.uploadFailed")));
    }
  } catch (error) {
    option.onError(error);
  }
};

const onReceiptRemove = (file, fileList) => {
  payReceiptFileList.value = fileList;
  if (file.url) {
    payReceiptUrls.value = payReceiptUrls.value.filter((item) => item !== file.url);
  }
};

const handleCancel = async (order) => {
  if (actionLoading.value) return;
  try {
    await ElMessageBox.confirm(
      t("courseOrder.confirmCancel"),
      t("courseOrder.confirmTitle"),
      {
        type: "warning",
        confirmButtonClass: "el-button--primary",
      }
    );
  } catch (error) {
    return;
  }
  actionLoading.value = true;
  try {
    await CancelCourseOrder(order.id);
    ElMessage.success(t("courseOrder.cancelOrder"));
    fetchOrders();
  } finally {
    actionLoading.value = false;
  }
};

const handleReview = (order) => {
  ElMessage.success(`${t("courseOrder.review")} ${order.orderSn}`);
};

const detailSections = computed(() => {
  if (!currentOrder.value) return [];
  const order = currentOrder.value;
  const withdraw = order.withdrawList?.[0];
  return [
    {
      title: t("courseOrder.orderInfoTitle"),
      items: [
        { label: t("courseOrder.orderNo"), value: order.orderSn || "--" },
        { label: t("courseOrder.orderTime"), value: formatDateTime(order.createTime) },
        { label: t("courseOrder.courseName"), value: order.courseName || "--" },
        { label: t("courseOrder.courseId"), value: order.courseId ?? "--" },
        { label: t("courseOrder.sessions"), value: renderSessions(order.courseNumber) },
        { label: t("courseOrder.validDays"), value: renderValidDays(order.effectiveDays) },
        { label: t("courseOrder.courseType"), value: getCourseTypeLabel(order.courseType) },
        { label: t("courseOrder.lessonMode"), value: getScheduleTypeLabel(order.scheduleType) },
        { label: t("courseOrder.coursePlan"), value: order.coursePlan || "--" },
        {
          label: t("courseOrder.orderUser"),
          value: mergeNameAndPhone(order.orderCreator?.username, order.orderCreator?.mobile),
        },
        {
          label: t("courseOrder.teacher"),
          value: mergeNameAndPhone(order.teacher, order.teacherPhone),
        },
        { label: t("courseOrder.student"), value: renderStudents(order.studentList) },
        { label: t("courseOrder.remark"), value: order.remark || "--" },
      ],
    },
    {
      title: t("courseOrder.paymentInfoTitle"),
      items: [
        { label: t("courseOrder.originalPrice"), value: formatAmount(order.price) },
        { label: t("courseOrder.discount"), value: formatAmount(order.preferentialPrice) },
        { label: t("courseOrder.receivable"), value: formatAmount(order.totalPayableAmount) },
        { label: t("courseOrder.paymentStatus"), value: getStatusText(order) },
        { label: t("courseOrder.paymentTime"), value: formatDateTime(order.payTime) },
        { label: t("courseOrder.paymentMethod"), value: getPaymentMethodLabel(order) },
        { label: t("courseOrder.transactionNo"), value: order.serialNumber || "--" },
        { label: t("courseOrder.receivedAmount"), value: formatAmount(order.totalPayableAmount) },
        { label: t("courseOrder.voucher"), value: "--" },
      ],
    },
    {
      title: t("courseOrder.refundInfoTitle"),
      items: [
        { label: t("courseOrder.refundTime"), value: formatDateTime(withdraw?.createTime) },
        { label: t("courseOrder.refundAmount"), value: formatAmount(withdraw?.withdrawMoney) },
        {
          label: t("courseOrder.refundLessons"),
          value:
            withdraw && withdraw.withdrawPeriod !== undefined
              ? t("courseOrder.sessionUnit", { count: withdraw.withdrawPeriod })
              : "--",
        },
        { label: t("courseOrder.refundRemark"), value: withdraw?.remark || "--" },
      ],
    },
  ];
});

onMounted(fetchOrders);
</script>

<template>
  <div class="admin course-order-page">
    <div class="admin-title">
      {{ t("courseOrder.title") }}
    </div>

    <div class="order-panel" v-loading="loading">
      <el-tabs v-model="activeStatus" class="order-tabs" @tab-change="handleTabChange">
        <el-tab-pane v-for="tab in tabs" :key="tab.id" :label="tab.text" :name="tab.id" />
      </el-tabs>

      <div v-if="orders.length" class="orders">
        <div v-for="order in orders" :key="order.id" class="order-card">
          <div class="order-card__header">
            <div class="header-top">
              <div class="header-left">
                <div class="header-item">
                  <span class="label">{{ t("courseOrder.orderNo") }}</span>
                  <span class="value">{{ order.orderSn }}</span>
                </div>
                <div class="header-item">
                  <span class="label">{{ t("courseOrder.orderTime") }}</span>
                  <span class="value">{{ formatDateTime(order.createTime) }}</span>
                </div>
              </div>
              <div class="header-right">
                <span class="label">{{ t("courseOrder.courseType") }}</span>
                <span class="value">{{ getCourseTypeLabel(order.courseType) }}</span>
              </div>
            </div>
          </div>

          <div class="order-card__body">
            <div class="order-col info-col">
              <div class="course-title">{{ order.courseName }}</div>
              <div class="course-sub">
                {{ t("courseOrder.courseId") }}：{{ order.courseId }}
              </div>

              <div class="info-list">
                <div class="info-row">
                  <span class="meta-label">{{ t("courseOrder.sessions") }}</span>
                  <span class="meta-value">{{ renderSessions(order.courseNumber) }}</span>
                  <span class="meta-label">{{ t("courseOrder.originalPrice") }}</span>
                  <span class="meta-value">{{ formatAmount(order.price) }}</span>
                  <span class="meta-label">{{ t("courseOrder.receivable") }}</span>
                  <span class="meta-value">{{ formatAmount(order.totalPayableAmount) }}</span>
                </div>
                <div class="info-row">
                  <span class="meta-label">{{ t("courseOrder.lessonMode") }}</span>
                  <span class="meta-value">{{ getScheduleTypeLabel(order.scheduleType) }}</span>
                  <span class="meta-label">{{ t("courseOrder.discount") }}</span>
                  <span class="meta-value discount">{{ formatAmount(order.preferentialPrice) }}</span>
                  <span class="meta-label">{{ t("courseOrder.paymentMethod") }}</span>
                  <span class="meta-value">{{ getPaymentMethodLabel(order) }}</span>
                </div>
                <div class="info-row">

                </div>
              </div>
            </div>

            <div class="order-col status-col">
              <div class="status-text" :class="getStatusClass(order)">
                {{ getStatusText(order) }}
              </div>
              <div class="status-row">
                <span class="meta-label">{{ t("courseOrder.paymentTime") }}</span>
                <span class="meta-value">{{ formatDate(order.payTime || "") }}</span>
              </div>
              <div>
                <div class="status-row">
                  <span class="meta-label">{{ t("courseOrder.orderUser") }}</span>
                  <span class="meta-value">{{ mergeNameAndPhone(order.orderCreator?.username,
                    order.orderCreator?.mobile) }}</span>
                </div>
                <div class="status-row">
                  <span class="meta-label">{{ t("courseOrder.student") }}</span>
                  <span class="meta-value">{{ renderStudents(order.studentList) }}</span>
                </div>
              </div>
            </div>

            <div class="order-col action-col">
              <div class="order-actions">
                <!-- 支付 -->
                <el-button v-if="getStatusKey(order.status) === 'pending'" class="ghost-primary" plain
                  @click="handlePay(order)">
                  {{ t("courseOrder.goPay") }}
                </el-button>
                <!-- 取消订单 -->
                <el-button v-if="getStatusKey(order.status) === 'pending'" plain :loading="actionLoading"
                  @click="handleCancel(order)">
                  {{ t("courseOrder.cancelOrder") }}
                </el-button>
                <!-- 评价 -->
                <!-- <el-button v-if="getStatusKey(order.status) === 'paid'" class="ghost-primary" plain
                  @click="handleReview(order)">
                  {{ t("courseOrder.review") }}
                </el-button> -->
                <!-- 查看详情 -->
                <el-button plain @click="openDetail(order)">
                  {{ t("courseOrder.viewDetail") }}
                </el-button>
              </div>
            </div>
          </div>
        </div>
        <div class="order-pagination-wrapper">
          <Pagination class="order-pagination" background layout="prev, pager, next" :total="total"
            v-model:current-page="currentPage" v-model:page-size="pageSize" @pagination-change="handlePageChange" />
        </div>
      </div>
      <el-empty v-else :description="t('courseOrder.empty')" />
    </div>

    <el-dialog v-model="payDialogVisible" :title="t('courseOrder.payDialogTitle')" width="520px" destroy-on-close
      :close-on-click-modal="false" @closed="resetPayDialog">
      <div class="pay-dialog-body">
        <div class="upload-label">{{ t("courseOrder.voucher") }}</div>
        <el-upload class="voucher-upload" :http-request="onReceiptUpload" :file-list="payReceiptFileList"
          list-type="picture-card" :before-upload="beforeReceiptUpload" :on-remove="onReceiptRemove"
          :disabled="paySubmitting" accept="image/*">
          <el-icon>
            <Plus />
          </el-icon>
          <template #tip>
            <div class="upload-tip">{{ t("courseOrder.paymentUploadTip") }}</div>
          </template>
        </el-upload>
        <div v-if="payUploadError" class="upload-error">{{ t("courseOrder.uploadRequired") }}</div>

        <div class="dialog-actions">
          <el-button @click="payDialogVisible = false" :disabled="paySubmitting">
            {{ t("courseOrder.cancel") }}
          </el-button>
          <el-button type="primary" :loading="paySubmitting" @click="submitPay">
            {{ t("courseOrder.confirmPay") }}
          </el-button>
        </div>
      </div>
    </el-dialog>

    <el-dialog v-model="dialogVisible" :title="t('courseOrder.detailTitle')" width="920px" destroy-on-close>
      <div v-if="currentOrder" class="detail-grid">
        <div v-for="section in detailSections" :key="section.title" class="detail-block">
          <div class="detail-title">{{ section.title }}</div>
          <div v-for="item in section.items" :key="item.label" class="detail-item">
            <span class="detail-label">{{ item.label }}</span>
            <span class="detail-value">{{ item.value }}</span>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped lang="less">
.course-order-page {
  font-family: PingFang HK, PingFang HK;

  .order-panel {
    padding: 16px 14px 20px;
    border-radius: 10px;
    background: #fff;
    box-shadow: 0 10px 30px rgba(17, 24, 39, 0.06);
  }

  .order-tabs {
    margin-bottom: 12px;

    :deep(.el-tabs__nav-wrap::after) {
      display: none;
    }
  }

  .order-card {
    border: 1px solid #f1f3f5;
    box-shadow: 0 8px 24px rgba(17, 24, 39, 0.06);
    border-radius: 10px;
    padding: 16px;
    background: #fff;
    margin-bottom: 12px;
  }

  .order-card__header {
    display: flex;
    flex-direction: column;
    gap: 6px;
    color: #606266;
    font-size: 13px;
  }

  .header-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
  }

  .header-left {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
  }


  .header-item,
  .header-right {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 500;
    color: #31373D;
  }

  .order-card__body {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr;
    gap: 16px;
    margin-top: 12px;
    align-items: start;
  }

  .order-col {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
  }

  .course-title {
    font-size: 16px;
    font-weight: 600;
    color: #1f2329;
    line-height: 1.4;
  }

  .course-sub {
    color: #909399;
    font-size: 13px;
  }

  .info-list {
    display: flex;
    flex-direction: column;
  }

  .info-row {
    display: grid;
    grid-template-columns: 0.6fr 1fr 0.6fr 1fr 0.6fr 1fr;
    align-items: center;
  }

  .meta-label {
    color: #909399;
    position: relative;
    white-space: nowrap;
    text-align: right;
  }

  .meta-label::after {
    content: "：";
  }

  .meta-value {
    color: #303133;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .meta-value.discount {
    color: #f56c6c;
  }

  .status-col {
    gap: 10px;
  }

  .status-text {
    display: inline-flex;
    align-items: center;
    font-weight: 600;
    font-size: 16px;
  }

  .status-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: #606266;
  }

  .status-pending {
    color: #f39c48;
  }

  .status-paid {
    color: #3bb18a;
  }

  .status-canceled,
  .status-refunded {
    color: #909399;
    border-color: #e4e7ed;
  }

  .status-review {
    color: #3b7cff;
    background: rgba(59, 124, 255, 0.1);
    border-color: rgba(59, 124, 255, 0.24);
  }

  .action-col {
    align-items: flex-end;
    justify-content: center;
  }

  .order-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .ghost-primary {
    color: #f77f3f;
    border-color: #f77f3f;
    background: rgba(247, 127, 63, 0.08);
  }

  .ghost-primary:hover {
    background: #f77f3f;
    color: #fff;
  }


  .order-pagination-wrapper {
    display: flex;
    justify-content: flex-start;
  }

  .order-pagination {
    margin-top: 12px;
    text-align: left;
  }

  .detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 12px 24px;
  }

  .detail-block {
    padding: 12px 14px;
  }

  .detail-title {
    font-weight: 600;
    color: #1f2329;
    margin-bottom: 8px;
  }

  .detail-item {
    display: flex;
    align-items: flex-start;
    font-size: 13px;
    color: #606266;
    margin-bottom: 6px;
  }

  .detail-label {
    color: #909399;
    width: 60px;
    position: relative;
    flex-shrink: 0;
  }

  .detail-label::after {
    content: "：";
    position: absolute;
    right: -6px;
  }

  .detail-value {
    color: #303133;
    margin-left: 12px;
    flex: 1;
    min-height: 18px;
    word-break: break-all;
  }

  .pay-dialog-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .upload-label {
    font-weight: 600;
    color: #1f2329;
  }

  .upload-tip {
    color: #909399;
    font-size: 12px;
    line-height: 1.4;
    margin-top: 6px;
  }

  .dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 8px;
  }

  .upload-error {
    color: #f56c6c;
    font-size: 12px;
    margin-top: -6px;
  }

  @media (max-width: 1200px) {
    .order-card__body {
      grid-template-columns: 1fr 1fr;
    }
  }

  @media (max-width: 768px) {
    .order-card__body {
      grid-template-columns: 1fr;
    }

    .info-row {
      grid-template-columns: auto 1fr;
      row-gap: 4px;
    }

    .action-col {
      align-items: flex-start;
    }

    .order-actions {
      justify-content: flex-start;
    }
  }
}
</style>
